type name = string;;
type age = int;;
type adress = string;;
type telephone = int;;
type contact = (name*age*adress*telephone);;
type agenda = contact list;;

let rec exist x = function
  |[]            -> false
  |e::l when e=x -> true
  |e::l          -> exist x l;;

let rec add_list x = function
  |[]            -> [x]
  |e::l when e<x -> e::add_list x l
  |e::l when e>x -> x::e::l
  |e::l          -> e::l;;

let rec remove_list x = function
  |[]            -> invalid_arg "La liste ne comprends pas cette valeur"
  |e::l when e=x -> l
  |e::l          -> e::remove_list x l;;

let rec map f = function
  |[]   -> []
  |e::l -> (f e)::map f l;;
map (function x -> x+1) [1;3;5;7;11];;

let rec iter f = function
  |[]   -> ()
  |e::l -> (f e; iter f l);;
iter (print_int) [1;3;5;7;11];;

let rec for_all f = function
  |[]   -> true
  |e::l -> (f e)&&for_all f l;;
for_all (function x -> x= 0) [0;0;0;0;0];;

let upper_case = function
  |x when x>='a'&&x<='z' -> char_of_int ( int_of_char x -32)
  |x                     -> x;;
upper_case 'c';;

let lower_case = function
  |x when x>='A'&&x<='Z' -> char_of_int ( int_of_char x +32)
  |x                     -> x;;
lower_case 'C';;

let string_of_char c = String.make 1 c;;

let string_apply f str = let x = (String.length str)-1 in
		       let rec apply func str x = function
			 |i when i<=x -> (string_of_char (f str.[i]))^(apply f str x (i+1))
			 |x -> ""
		       in apply f str x 0;;

let string_uppercase str = string_apply upper_case str;;
string_uppercase "Hello";;

let string_lowercase str = string_apply lower_case str;;
string_lowercase "HELLO";;

let convert_first_maj str= let long=String.length str -1 in
			   let rec maj str long= function
			     |i when i=0 -> (string_of_char (upper_case (str.[i])))^(maj str long (i+1))
			     |i when i<=long -> (string_of_char (str.[i]))^(maj str long (i+1))
			     |_ -> ""
			   in maj str long 0;;
convert_first_maj "hello";;


let create_contact (name,age,adress,telephone) = (convert_first_maj (string_lowercase (name)),age,adress,telephone);;

let manage_contact func contact agenda = func contact agenda;;

let rec add_contact contact agenda = match (agenda,contact) with
  |((a,b,c,d)::l,(e,f,g,h)) -> if a<e then (a,b,c,d)::(add_contact (e,f,g,h) l)
                               else if a=e then failwith "Ce contact existe deja"
			       else (create_contact (e,f,g,h))::(a,b,c,d)::l
  |([],(e,f,g,h)) -> [create_contact (e,f,g,h)];;
